﻿
//
// Clean up XML
//
// Could still use better formatting of table rows and cells
//

//ParseXml.InlineRx = /^(a|u|b|i|br|strike|cite|code|strong|img|span|strong|em|sp|sub|sup|q|big|small|tt|title|input|button)$/;
ParseXml.InlineRx = /^(a|u|b|i|strike|cite|code|strong|span|strong|em|sp|sub|sup|q|big|small|tt)$/;

ParseXml.Transform = function (txt, map) {
    //options = options || {};
    //options.hasCyClass = /class=".*?\bcy\b.*?"/.test(txt);
    return ProcessXml.Process(txt, map).output;
};

//HtmlTransform = function (options) {
//    this.options = options || {};
//    this.level = 1;
//    this.blk = 0;
//};

HtmlTransform.prototype.any = function (po) {
    // filter out mojo classed tags
    var cls = (po.getAttr('class') || '').sanitizeClass();

    if (this.options.Filter && this.options.Filter(po, cls))
        return;

    po.setAttr('class', cls || null);
    var stl = (po.getAttr('style') || '').sanitizeStyle();
    po.setAttr('style', stl || null);

    // filter attributes
    po.setAttr('aria-disabled', null);

    //this.$autoConfigure(po);

    if (ParseXml.InlineRx.test(po.tagName)) {
        po.append(this.$front(po) + po.buildTag());
        this.blk = 0;
        ParseXml.ParseRecur(po);
        po.append(po.getEndTag());
        return;
    }
    po.append(po.getFront().reduce() + this.$indent(po) + po.buildTag());
    this.blk++;
    this.level++;
    ParseXml.ParseRecur(po);
    this.level--;
    this.blk = 0;
    var en = po.getEndTag();
    if (en) po.append((po.hasInner() ? this.$indent(po) : '') + en);
};

HtmlTransform.prototype.area = function (po) {
    po.append(this.$front(po));
};

HtmlTransform.prototype.comment = function (po) {
    po.append(po.getFront().reduce().replace(/\s+$/, '') + '\n' + po.getOuter() + '\n');
};

HtmlTransform.prototype.script = function (po) {
    var i = po.getInner();
    if (i) {
        po.setAttr('type', po.getAttr('type') || 'text/javascript');
        var front = po.getFront().extract(/([ \t]+)$/);
        po.append('\n' + po.getFront().reduce() + '\n' + front + po.buildTag() + i.replace(/\s+$/, '') + '\n' + front + po.getEndTag() + '\n');
    }
    else
        po.append(po.getFront().reduce() + this.$indent(po) + po.getOuter());
};

HtmlTransform.prototype.style = function (po) {
    //if (/-mojoStyleSheet$/.test(po.getAttr('title') || '')) return;
    var front = po.getFront().extract(/([ \t]+)$/), i = po.getInner();
    po.append('\n' + po.getFront().reduce() + '\n' + front + po.getTag() + i.replace(/\s+$/, '') + '\n' + front + po.getEndTag() + '\n');
};

HtmlTransform.prototype.link = function (po) {
    if (po.getAttr('rev') == 'stylesheet') return;
    this.any(po);
};

HtmlTransform.prototype.html = function (po) {
    this.level = 0;
    this.any(po);
};

HtmlTransform.prototype.title = function (po) {
    this.$trimmedInner(po)
};
HtmlTransform.prototype.button = function (po) {
    this.$trimmedInner(po)
};

HtmlTransform.prototype.br = function (po) {
    po.append(po.getFront().reduce().replace(/\s+$/, '') + po.getOuter() + this.$indent(po));
};

HtmlTransform.prototype.$doctype = function (po) {
    po.append(po.getOuter());
};

HtmlTransform.prototype.$trimmedInner = function (po) {
    po.append(po.getFront().reduce() + this.$indent(po) + po.getTag() + po.getInner().trim() + po.getEndTag());
};

HtmlTransform.prototype.$indent = function (po) {
    var i = this.level, ot = '';
    if (i > 0) while (i--) ot += '\t';
    return (po.buffer() && !/\n[ \t]*$/.test(po.buffer()) ? '\n' : '') + ot;
};

HtmlTransform.prototype.$front = function (po) {
    var f = po.getFront().reduce();
    if (f) {
        if (this.blk || /\n[ \t]*$/.test(po.buffer())) {
            return this.$indent(po) + f.trim();
        }
        return f;
    }
    if (this.blk) return this.$indent(po);
    return '';
};

String.prototype.shrinkSpace = function () {
    return this.replace(/\s+/g, ' ').replace(/^\s|\s$/g, '')
};
String.prototype.sanitizeStyle = function () {
    var stl = this.replace(/(background-color:\s*?(rgba\(0, 0, 0, 0\)|transparent))[;\s]*?/, '');
    stl = stl.reduceQuad('margin', ['margin-top', 'margin-right', 'margin-bottom', 'margin-left']);
    stl = stl.reduceQuad('padding', ['padding-top', 'padding-right', 'padding-bottom', 'padding-left']);
    stl = stl.reduceQuad('border-style', ['border-top-style', 'border-right-style', 'border-bottom-style', 'border-left-style']);
    stl = stl.reduceQuad('border-width', ['border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width']);
    stl = stl.reduceQuad('border-color', ['border-top-color', 'border-right-color', 'border-bottom-color', 'border-left-color']);
    stl = stl.reduceQuad('border-radius', ['border-top-left-radius', 'border-top-right-radius', 'border-bottom-left-radius', 'border-bottom-right-radius'], function (a, b, c, d) {
        a = a.split(' ');
        b = b.split(' ');
        c = c.split(' ');
        d = d.split(' ');
        var ot = '';
        ot += ' -webkit-border-radius: ' + a[0] + ';';
        ot += ' -moz-border-radius: ' + a[0] + ' ' + b[0] + ' ' + c[0] + ' ' + d[0] + ' / ' + (a[1] || a[0]) + ' ' + (b[1] || b[0]) + ' ' + (c[1] || c[0]) + ' ' + (d[1] || d[0]) + ';';
        ot += ' border-radius: ' + a[0] + ' ' + b[0] + ' ' + c[0] + ' ' + d[0] + ' / ' + (a[1] || a[0]) + ' ' + (b[1] || b[0]) + ' ' + (c[1] || c[0]) + ' ' + (d[1] || d[0]) + ';';
        return ot;
    }, function (stl, dfault) {
        stl = dfault(stl);
        stl = stl.replace(/\s*-moz-border-radius\s*:[^;]+(;|$)/, '');
        stl = stl.replace(/\s*-webkit-border-radius\s*:[^;]+(;|$)/, '');
        return stl;
    });
    return stl.replace(/[;\s]+$/, '');
};
String.prototype.sanitizeClass = function () {
    return this.replace(/\b(mojoShowSurface|placeholder|nv-.+?|ui-.+?|NV-.+?)\b/g, '').shrinkSpace()
};

String.prototype.reduceQuad = function (base, s4, builder, filter) {
    builder = builder || function (a, b, c, d) {
        if (a == b && b == c && c == d)
            return base + ': ' + a + ';';
        else if (a == c && b == d)
            return base + ': ' + a + ' ' + b + ';';
        return base + ': ' + a + ' ' + b + ' ' + c + ' ' + d + ';';
    };
    var a = '\\s*:\\s*([^;]+)(;|$)';
    var a1 = '\\s*' + s4[0].escapeRegExp() + a;
    var a2 = '\\s*' + s4[1].escapeRegExp() + a;
    var a3 = '\\s*' + s4[2].escapeRegExp() + a;
    var a4 = '\\s*' + s4[3].escapeRegExp() + a;
    var r1 = this.match(new RegExp(a1, 'i'));
    var r2 = this.match(new RegExp(a2, 'i'));
    var r3 = this.match(new RegExp(a3, 'i'));
    var r4 = this.match(new RegExp(a4, 'i'));
    r1 = r1 ? r1[1].replace(/\s$/, '') : null;
    r2 = r2 ? r2[1].replace(/\s$/, '') : null;
    r3 = r3 ? r3[1].replace(/\s$/, '') : null;
    r4 = r4 ? r4[1].replace(/\s$/, '') : null;
    if (r1 && r2 && r3 && r4) {
        var my = this;
        var dfault = function (stl) {
            return my.replace(RegExp(a1 + '|' + a2 + '|' + a3 + '|' + a4, 'ig'), '').trim();
        }
        a = filter ? filter(my, dfault) : dfault(my);
        var nw = builder(r1, r2, r3, r4).trim();
        return (a.length && a.substr(a.length - 1) == ';') || !a.length ? (a.length ? a + ' ' : '') + nw : a + '; ' + nw;
    }
    return this;
};

String.prototype.escapeRegExp = function() {
    return this.replace( /([-.*+?^${}()|[\]\/\\])/g , '\\$1');
};
